package org.jeecg.modules.wechat.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.shiro.WxUserToken;
import org.jeecg.modules.wechat.vo.UserInfoVO;
import org.jeecg.modules.wechat.api.WxMiniApi;
import org.jeecg.constant.WXConstant;
import org.jeecg.modules.wechat.dto.UserInfoDto;
import org.jeecg.modules.wechat.entity.WxUser;
import org.jeecg.modules.wechat.service.IWxUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;


/**
 * TODO: 微信登录和授权相关
 *`
 * @author Zhang Hao yu
 * @date 2020/11/10 13:54
 */
@Slf4j
@RestController
@RequestMapping("/wechatLogin")
public class WXLoginController {

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private WxMiniApi wxMiniApi;
    @Autowired
    private IWxUserService wxUserService;
    /**
     * TODO:
     *
     * @author ZhangHaoyu
     * @param infoDto 前端传入的参数信息，参考 org.jeecg.modules.wechat.dto.UserInfoDto
     * @return org.jeecg.common.api.vo.Result<?>
     */
    @ApiOperation("微信登录")
    @PostMapping("/login")
    public Result<?> login(@RequestBody UserInfoDto infoDto){
        String code = infoDto.getCode();
        // 获取不隐密的信息
        String rawData = infoDto.getRawData();

        if (StringUtils.isEmpty(code) || StringUtils.isEmpty(rawData)) {
            return Result.error("参数不能为空");
        }

        // 调用接口获取openid 获取session_key
        JSONObject jsonObject = wxMiniApi.authCode2Session(WXConstant.WX_APPID, WXConstant.WX_SECRET, code);
        if (jsonObject==null){
            return Result.error("参数错误！");
        }
        // 获取openid
        String openid = jsonObject.getString("openid");
        // 获取session_key  没用？？？？ 不去解密用户信息
        String sessionKey = jsonObject.getString("session_key");
        WxUser wxUser = new WxUser();
        wxUser.setOpenId(openid);
        WxUserToken token = new WxUserToken(wxUser);
        token.setRawData(rawData);
        // 注册登录真正的方法
        try {
            SecurityUtils.getSubject().login(token);
        } catch (AuthenticationException e) {
            log.info("=========新用户注册===========");
            e.printStackTrace();
        }
        WxUser user = token.getUser();
        String tok = JwtUtil.sign(openid, sessionKey);
        // 设置返回值
        UserInfoVO userInfoVO = new UserInfoVO(tok,user);
        // 把token放到redis中
        redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + tok, tok+WXConstant.WX_TOKEN_SEPARATOR+sessionKey);
        // 设置超时时间
        redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + tok, JwtUtil.EXPIRE_TIME / 1000);
        System.out.println(userInfoVO);
        return Result.OK("获取信息成功！",userInfoVO);
    }

    /**
     * TODO:  jwt生成token，token放入redis，返回token  已废弃！
     *
     *
     * @author ZhangHaoyu
     * @param openid
     * @param sessionKey
     * @return java.lang.String  token
     */
    private String produceAndSetToken(String openid,String sessionKey){
        // 生成token,放入redis中
        String token = JwtUtil.sign(openid,sessionKey);
        StringBuilder sb = new StringBuilder();
        sb.append(openid).append(WXConstant.WX_TOKEN_SEPARATOR).append(sessionKey);
        String openid_sessionKey = sb.toString();
        redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, openid_sessionKey);
        // 设置超时时间
        redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME / 1000);
        return token;
    }

    /**
     * TODO: 获取request里的token，判断用户登录是否有效
     *
     *
     * @author ZhangHaoyu
     * @param request 请求
     * @return org.jeecg.common.api.vo.Result<?>
     */
    @ApiOperation("检查token是否有效")
    @PostMapping("/checkToken")
    public Result<?> checkToken(HttpServletRequest request){
        String token = request.getParameter("token");
        if (token ==null){
            token = request.getHeader("token");
        }
        String stringToken = (String) redisUtil.get(CommonConstant.PREFIX_USER_TOKEN + token);
        System.out.println("stringToken"+stringToken);
        if (stringToken== null || "".equals(stringToken)){
            return Result.error("token失效，重新登录");
        }
        String openId = JwtUtil.getUsername(stringToken);
        WxUser user = wxUserService.getOne(new LambdaQueryWrapper<WxUser>().eq(WxUser::getOpenId, openId));
        return Result.OK(user);
    }
}